--- %%NOBANNER%% -->
/*-------------------<-- Start of Description-->---------------------\
| create SAS dataset &outdata using LENGTH statement for numeric vars|
| that optimizes the variable to the fewest # of bytes needed to |
| maintain the accuracy of the values contained in the variable; |
|---------------------<-- End of Description-->----------------------|
|--------------------------------------------------------------------|
|------------<-- Start of Files or Arguments Needed-->---------------|
| Arguments neede: |
| indata : input dataset name; Required; |
| outdata: Output dataset name; Required; |
| Note: the output dataset name cannot be the same as input dataset; |
|---------------<-- End of Files Arguments Needed-->-----------------|
|--------------------------------------------------------------------|
|------------------<-- Start of Files Created-->---------------------|
| Example: |
| data one ; |
| format y x 11.6; |
| x=1.111; y=2.222;output; |
| x=11.1234; y=1.1;output; |
| run; |
| %resizen(one); %prcnt(one); %print(one); |
| Usage: %resizen(indata, outdata); |
\-------------------<-- End of Files Created-->---------------------*/
%macro resizen/parmbuff;
/*--------------------------------------------\
| Copy Right: Duo Zhou; |
| Created: 3-11-2002 9:42pm; |
| Purpose: Minimize numeric variables length; |
\--------------------------------------------*/
%local I sqzlength _VAR_NAMES_ _VAR_N_ _MAX_LEN_ _oriord_;
%let inbuff=%qscan(&syspbuff,1,%str((),));
%let outbuff=%qscan(&syspbuff,2,%str((),));
%let linesize = %SYSFUNC(GETOPTION(linesize));
%if (%index(%quote(&syspbuff),%quote(=))) %then %do;
%if (%index(%quote(&inbuff),%quote(=))) %then %do;
%if (%index(%quote(%upcase(%sysfunc(compress(%quote(&inbuff))))),%quote(INDATA=))) %then %do;
%let indata=%qscan(&inbuff,2,%str(=));
%if (%index(%quote(&outbuff),%quote(=))) %then %do;
%if (not %index(%quote(%upcase(%sysfunc(compress(%quote(&outbuff))))),%quote(OUTDATA=))) %then %do;
%put ==> Alert! Keyword parameter "%qscan(&outbuff,1,%str(=))" is not defined!;
%end;
%else %do;
%let outdata=%qscan(&outbuff,2,%str(=));
%end;
%end;
%else %do;
%let outdata=&outbuff;
%end;
%end;
%else %if (%index(%quote(%upcase(%sysfunc(compress(%quote(&inbuff))))),%quote(OUTDATA=))) %then %do;
%let outdata=%qscan(&inbuff,2,%str(=));
%if (%index(%quote(&outbuff),%quote(=))) %then %do;
%if (not %index(%quote(%upcase(%sysfunc(compress(%quote(&outbuff))))),%quote(INDATA=))) %then %do;
%put ==> Alert! Keyword parameter "%qscan(&outbuff,1,%str(=))" is not defined!;
%end;
%else %do;
%let indata=%qscan(&outbuff,2,%str(=));
%end;
%end;
%else %do;
%let indata=&outbuff;
%end;
%end;
%else %put ==> Alert! Keyword parameter "%qscan(&inbuff,1,%str(=))" is not defined!;
%end;
%else %if (%index(%quote(&outbuff),%quote(=))) %then %do;
%if (%index(%quote(%upcase(%sysfunc(compress(%quote(&outbuff))))),%quote(INDATA=))) %then %do;
%let indata=%qscan(&outbuff,2,%str(=));
%let outdata=&inbuff;
%end;
%else %if (%index(%quote(%upcase(%sysfunc(compress(%quote(&outbuff))))),%quote(OUTDATA=))) %then %do;
%let indata=&inbuff;
%let outdata=%qscan(&outbuff,2,%str(=));
%end;
%else %do;
%put ==> Alert! Keyword parameter "%qscan(&outbuff,1,%str(=))" is not defined!;
%end;
%end;
%end;
%else %do;
%let indata=&inbuff;
%let outdata=&outbuff;
%end;
%if (%quote(&indata) eq) %then %do;
%put ==> Alert! No input dataset is to be resized!;
%goto L9999;
%end;
%if (%quote(&outdata) eq) %then %do;
%let outdata=&indata;
%end;
%put *=================================================* ;
%put | Beginning to resize numeric variables. | ;
%put | Please be patient because this process may | ;
%put | require a lot of execution time. | ;
%put *=================================================* ;
%let _VAR_N_ = 0 ;
/*##########################################################*/
/* begin executable code */
/*##########################################################*/
proc contents data=&indata memtype=data noprint out=_cntnts_; run;
proc sql noprint;
select count(distinct name), max(length) into: _VAR_N_, :_MAX_LEN_
from _cntnts_
where type=1;
select distinct name into: _VAR_NAMES_ separated by ", "
from _cntnts_
where type=1;
select name into : _oriord_ separated by ' '
from _cntnts_
order by varnum;
quit;
%let best=Best%sysfunc(trimn(%sysfunc(left(&_MAX_LEN_))));
/* in case there are NO numeric vars in dataset, */
/* stop further processing */
%if (%quote(&_VAR_N_) = %quote(0)) %then %do;
%put *==================================* ;
%put | ERROR from resizen: | ;
%put | No numeric variables in dataset. | ;
%put | Execution terminating forthwith. | ;
%put *==================================* ;
%goto L9999 ;
%end ;
/* create macro vars containing variable name */
/* process variables of numeric type only */
data _null_;
set _cntnts_;
if type = 1;
var_no + 1;
call symput( '_VAR_'||left( put( var_no, 5. )), name);
run;
/* Compute the minimum length and format for each numeric variable*/
proc sql noprint;
select max(length(trim(left(put(&_VAR_1, &best..))))),
max(length(trim(left(scan(put(&_VAR_1, &best..), 2, '.')))))
%if &_VAR_N_ > 1 %then %do;
%do _I_=2 %to &_VAR_N_;
, max(length(trim(left(put(&&_VAR_&_I_, &best..))))), max(length(trim(left(scan(put(&&_VAR_&_I_, &best..), 2, '.')))))
%end;
%end;
into: FMTL1, :FMTD1
%if &_VAR_N_ > 1 %then %do;
%do _I_=2 %to &_VAR_N_;
, :FMTL&_I_, :FMTD&_I_
%end;
%end;
from &indata;
quit;
/* initialize SQZLENTH global macro var */
%let SQZLENTH = LENGTH ; %let SQZFMT=FORMAT ;
%do I = 1 %to &_VAR_N_ ;
%if (%quote(&&FMTD&I) ne ) %then %do;
%let SQZLENTH = &SQZLENTH %qtrim(%left(&&_VAR_&I)) %trim(%left(%_max(%eval(&&FMTL&I+&&FMTD&I) 3)));
%let SQZFMT=&SQZFMT %qtrim(%left(&&_VAR_&I)) %trim(%left(%eval(&&FMTL&I+&&FMTD&I))).%trim(%left(&&FMTD&I));
%end;
%else %do;
%if (&&FMTL&I lt 3) %then %let SQZLENTH = &SQZLENTH %qtrim(%left( &&_VAR_&I )) %trim(%left(3));
%else %if (&&FMTL&I gt 8) %then %let SQZLENTH = &SQZLENTH %qtrim(%left( &&_VAR_&I )) %trim(%left(8));
%else %let SQZLENTH = &SQZLENTH %qtrim(%left( &&_VAR_&I )) %trim(%left(&&FMTL&I));
%let SQZFMT=&SQZFMT %qtrim(%left(&&_VAR_&I)) %trim(%left(&&FMTL&I)).;
%end;
%end;
/* apply SQZLENTH to incoming data, create output dataset */
data &outdata;
retain &_oriord_;
&SQZLENTH;
&SQZFMT;
set &indata;
run;
proc datasets nolist ; delete _cntnts_ _tmp_; run;
%L9999:
%mend resizen;